﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cool.Application.System.RoleService;
using Cool.Application.System.RoleService.Dtos;
using Cool.Core.Entities.System;
using Cool.Core.Enums;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Cool.Core.DataExtensions;
using Cool.Core.Managers;

namespace Cool.Application.System.RoleService
{
    [Authorize]
    [ApiDescriptionSettings("System")]
    [Route("api/system/[controller]")]
    public class RoleService:IRoleService, ITransient, IDynamicApiController
    {

        /// <summary>
        /// 功能仓储
        /// </summary>
        private readonly IRepository<SysRole> _roleRepository;

        /// <summary>
        /// 角色菜单仓储
        /// </summary>
        private readonly IRepository<SysRoleMenu> _roleMenuRepository;

        /// <summary>
        /// 角色部门仓储
        /// </summary>
        private readonly IRepository<SysRoleDept> _roleDeptRepository;

        /// <summary>
        /// 用户角色仓储
        /// </summary>
        private readonly IRepository<SysUserRole> _userRoleRepository;


        /// <summary>
        /// 用户仓储
        /// </summary>
        private readonly IRepository<SysUser> _userRepository;
        /// <summary>
        /// 用户管理类
        /// </summary>
        private readonly IUserManager _userManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="roleRepository"></param>
        /// <param name="roleMenuRepository"></param>
        public RoleService(IRepository<SysUser> userRepository, 
            IUserManager userManager, 
            IRepository<SysUserRole> userRoleRepository, 
            IRepository<SysRole> roleRepository, 
            IRepository<SysRoleMenu> roleMenuRepository, 
            IRepository<SysRoleDept> roleDeptRepository)
        {
            _roleRepository = roleRepository;
            _userManager = userManager;
            _roleMenuRepository = roleMenuRepository;
            _roleDeptRepository = roleDeptRepository;
            _userRepository = userRepository;
            _userRoleRepository = userRoleRepository;
        }


        public async Task<PagedList<RoleReturnDto>> GetListAsync([FromQuery, Required] RoleTableSearchDto roleTableSearchDto)
        {
            var hasRoleName = !string.IsNullOrEmpty(roleTableSearchDto.RoleName?.Trim());
            var hasStatus = roleTableSearchDto.Status != null;
            var hasRoleKey=!string.IsNullOrEmpty(roleTableSearchDto.RoleKey?.Trim());

            

            //TODO:linq时间查询功能无效
            var roleTreeList = await(from role in  _roleRepository.Where(
                (hasRoleName, u => EF.Functions.Like(u.RoleName, $"%{roleTableSearchDto.RoleName.Trim()}%")),
                (hasRoleKey, u => EF.Functions.Like(u.RoleKey, $"%{roleTableSearchDto.RoleKey.Trim()}%")),
                (hasStatus, u => u.Status == roleTableSearchDto.Status),
                (roleTableSearchDto.BeginTime!=null, u => u.CreatedTime >= roleTableSearchDto.BeginTime),
                (roleTableSearchDto.EndTime != null, u => u.CreatedTime <= roleTableSearchDto.EndTime)
                ) join userRole in _userRoleRepository.AsQueryable() on role.Id equals userRole.RoleId into result
                    from userRole in result.DefaultIfEmpty()
                    join user in _userRepository.AsQueryable() on userRole.UserId equals user.Id into users
                    from user in users.DefaultIfEmpty()
                    select new RoleReturnDto
                    {
                        Id=role.Id,
                        RoleKey=role.RoleKey,
                        RoleName=role.RoleName,
                        CreatedTime=role.CreatedTime,
                        DataScope=role.DataScope,
                        DeptId=user.DeptId,
                        OrderNum=role.OrderNum,
                        Status=role.Status,
                        UserId=role.CreatedBy.Value
                    }
                    ).ToDeptPermsList().ToPagedListAsync(roleTableSearchDto.PageIndex, roleTableSearchDto.PageSize);
            return roleTreeList;
        }


        public async Task<SysRole> GetAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的角色 Id")] int roleId)
        {
            return await _roleRepository.FindAsync(roleId);
        }

        public async Task<SysRole> AddAsync([Required] RoleInputDto roleDto)
        {
            var addRole = roleDto.Adapt<SysRole>();
            using (var transaction = _userRepository.Database.BeginTransaction())
            {
                try
                {
                    var entryEntity = await _roleRepository.InsertAsync(addRole);
                    roleDto.Id = entryEntity.Entity.Id;
                    SaveRoleInfo(roleDto);
                    // 提交事务
                    transaction.Commit();
                    return entryEntity.Entity;
                }
                catch (Exception e)
                {
                    transaction.Rollback();
                    return null;
                }
            }

            
        }

        public async Task UpdateAsync([Required] RoleInputDto roleDto)
        {
            var updateRole = roleDto.Adapt<SysRole>();
            using (var transaction = _roleRepository.Database.BeginTransaction())
            {
                try
                {
                    SaveRoleInfo(roleDto);
                    await _roleRepository.UpdateExcludeAsync(updateRole, new[] { nameof(SysRole.IsDeleted), nameof(SysRole.CreatedTime) }, ignoreNullValues: true);
                    // 提交事务
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    transaction.Rollback();
                }
            }
        }

        private void SaveRoleInfo(RoleInputDto roleDto)
        {
            if (roleDto.deptIds != null && roleDto.deptIds.Count > 0)
            {
                var rowEffects = $"delete from sysroledept where RoleId={roleDto.Id}".SqlNonQuery();

                _roleDeptRepository.InsertNow(
                    roleDto.deptIds.Select(p => new SysRoleDept(){DeptId = p, RoleId = roleDto.Id}));

            }
            if (roleDto.menuIds != null && roleDto.menuIds.Count > 0)
            {
                var rowEffects = $"delete from sysrolemenu where RoleId={roleDto.Id}".SqlNonQuery();

                _roleMenuRepository.InsertNow(
                    roleDto.menuIds.Select(p => new SysRoleMenu() { MenuId = p, RoleId = roleDto.Id }));
            }
        }
        public async Task DeleteAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的角色 Id")] int roleId)
        {
            var deleteMenu = await _roleRepository.FindAsync(roleId);
            _ = deleteMenu ?? throw Oops.Oh(SystemErrorCodes.u1002);

            // 软/假删除
            deleteMenu.IsDeleted = true;
        }
    }
}
